package com.info33.platform.business.app.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.info33.platform.business.app.dao.AppRoleDao;
import com.info33.platform.business.app.dao.AppRoleUserDao;
import com.info33.platform.business.app.dao.AppTenantUserDao;
import com.info33.platform.business.app.dto.AppTenantUserDTO;
import com.info33.platform.business.app.entity.AppTenantUser;
import com.info33.platform.business.app.service.AppRoleUserService;
import com.info33.platform.business.app.service.AppTenantUserService;
import com.info33.platform.business.app.util.excel.ExportExcel;
import com.info33.platform.business.app.vo.AppTenantUserVO;
import com.info33.platform.common.constant.TableConstant;
import com.info33.platform.common.exception.ResultException;
import com.info33.platform.common.exception.TransactionalException;
import com.info33.platform.common.mvc.vo.Result;
import com.info33.platform.system.dao.SysTenantDao;
import com.info33.platform.system.dto.SysUserDTO;
import com.info33.platform.system.entity.SysTenant;
import com.info33.platform.system.entity.SysUser;
import com.info33.platform.system.service.SysUserEducationService;
import com.info33.platform.system.service.SysUserProfileService;
import com.info33.platform.system.service.SysUserService;
import com.info33.platform.system.vo.SysUserVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author admin
 */
@Service
public class AppTenantUserServiceImpl extends ServiceImpl<AppTenantUserDao, AppTenantUser> implements AppTenantUserService {

    @Autowired
    private AppTenantUserDao appTenantUserDao;
    @Autowired
    private SysTenantDao sysTenantDao;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private AppRoleUserService appRoleUserService;
    @Autowired
    SysUserEducationService sysUserEducationService;
    @Autowired
    AppRoleUserDao appRoleUserDao;
    @Autowired
    AppRoleDao appRoleDao;
    @Autowired
    private SysUserProfileService sysUserProfileService;


    @Override
    public IPage<AppTenantUserVO> pcPage(Page<AppTenantUser> page, AppTenantUserDTO dto, SysUserVO sysCurrentUser) {
        return appTenantUserDao.pcPage(page, dto, sysCurrentUser.getTenant().getId());
    }

    @Override
    public AppTenantUserVO pcDetail(Long uid) {
        return appTenantUserDao.pcDetail(uid);
    }

    @Override
    public List<AppTenantUserVO> appTenants(SysUserVO appCurrentUser) {
        List<AppTenantUserVO> list = appTenantUserDao.appTenants(appCurrentUser);
        list.forEach(l -> l.getTenantVO().setCurrent(l.getTenantId().equals(appCurrentUser.getTenant().getId()) ? Boolean.TRUE : Boolean.FALSE));
        return list;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Result<Object> pcSwitch(Long id, SysUserVO currentUser) {
        AppTenantUserVO newTenant = appTenantUserDao.checkPrincipal(id);
        if (Boolean.FALSE.equals(newTenant.getTenantVO().getActivate())) {
            return Result.error(newTenant.getTenantVO().getName() + " 租户已被冻结,无法切换");
        }
        if (Boolean.TRUE.equals(newTenant.getLocked())) {
            return Result.error("您的账号在此租户下已经被冻结，无法切换至 " + newTenant.getTenantVO().getName() + " 租户");
        }
        if (Boolean.TRUE.equals(newTenant.getPrincipal()) && Boolean.TRUE.equals(newTenant.getTenantVO().getActivate())) {
            return Result.ok("此租户，已是主要租户");
        }
        // 将其它租户切换成非主要租户
        List<AppTenantUser> oldList = appTenantUserDao.selectList(new QueryWrapper<AppTenantUser>()
                .select(TableConstant.ID, "0 AS principal")
                .eq("user_id", currentUser.getId())
                .eq("principal", 1));
        if (!ObjectUtils.isEmpty(oldList)
                && Boolean.FALSE.equals(this.updateBatchById(oldList))) {
            return Result.error(Result.RESULT_ERROR_PUBLIC_MSG);
        }
        // 选择的租户切换为主租户
        AppTenantUser entity = new AppTenantUser();
        entity.setPrincipal(Boolean.TRUE);
        entity.setId(id);
        if (appTenantUserDao.updateById(entity) != 1) {
            throw new TransactionalException();
        }
        return Result.ok();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Result<Object> pcEdit(AppTenantUserDTO dto) {
        SysUserVO entity = new SysUserVO();
        BeanUtils.copyProperties(dto.getUserDTO(), entity);
        SysUser forecast = sysUserService.getOne(new QueryWrapper<SysUser>()
                .select(TableConstant.ID)
                .eq("login_name", entity.getLoginName())
                .ne(TableConstant.ID, entity.getId())
                .last(TableConstant.LIMIT_ONE));
        if (!ObjectUtils.isEmpty(forecast)) {
            return Result.error(entity.getLoginName() + " 此登录名，已经存在不可使用");
        }
        if (Boolean.FALSE.equals(sysUserService.updateById(entity))) {
            return Result.error(Result.RESULT_ERROR_PUBLIC_MSG);
        }
        AppTenantUser appTenantUser = new AppTenantUser();
        BeanUtils.copyProperties(dto, appTenantUser);
        if (appTenantUserDao.updateById(appTenantUser) != 1) {
            throw new TransactionalException();
        }
        appRoleUserService.pcBind(dto.getId(), dto.getRoleIds());
        return Result.ok();
    }

    @Override
    public Map<Long, Date> onLineUser() {
//        Collection<Session> sessions = sessionDAO.getActiveSessions();
//        Map<Long, Date> returnMap = new ConcurrentHashMap<>(sessions.size());
//        sessions.parallelStream().forEach(l -> {
//            if (!ObjectUtils.isEmpty(l) && !ObjectUtils.isEmpty(l.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY))) {
//                SimplePrincipalCollection principalCollection = (SimplePrincipalCollection) l.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
//                Object primaryPrincipal = principalCollection.getPrimaryPrincipal();
//                if (primaryPrincipal instanceof SysUserVO) {
//                    SysUserVO appUserVO = (SysUserVO) principalCollection.getPrimaryPrincipal();
//                    if (!ObjectUtils.isEmpty(appUserVO.getAppTenantUserVO())) {
//                        returnMap.put(appUserVO.getAppTenantUserVO().getId(), l.getStartTimestamp());
//                    }
//                }
//            }
//        });
//        return returnMap;
        return null;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Long register(SysUserDTO dto, Long tid) {
        Long uid = sysUserService
                .register(dto)
                .getId();
        AppTenantUser tenantUser = appTenantUserDao.selectOne(new QueryWrapper<AppTenantUser>()
                .select(TableConstant.ID)
                .eq("user_id", uid)
                .eq(TableConstant.TENANT_ID, tid)
                .last(TableConstant.LIMIT_ONE));
        if (!ObjectUtils.isEmpty(tenantUser)) {
            if (Boolean.TRUE.equals(tenantUser.getLocked())) {
                throw new ResultException("该账号在此租户被冻结！");
            }
            return tenantUser.getId();
        }
        // 首次绑定
        tenantUser = new AppTenantUser();
        tenantUser.setUserId(uid);
        tenantUser.setTenantId(tid);
        if (appTenantUserDao.installOneWithTenantId(tenantUser) != 1) {
            throw new TransactionalException();
        }
        // 创建用户拓展信息
        sysUserProfileService.register(dto.getUserProfileDTO(), tid, uid);
        return tenantUser.getId();
    }

    @Override
    public Result<Object> appChange(Long atuId, SysUserVO currentUser) {
        AppTenantUser appTenantUser = this.getById(atuId);
        if (!currentUser.getId().equals(appTenantUser.getUserId())) {
            return Result.error(Result.RESULT_ERROR_PUBLIC_MSG);
        }
        if (Boolean.TRUE.equals(appTenantUser.getLocked())) {
            return Result.error("您在此租户下已经被锁定，无法登录");
        }
        SysTenant sysTenant = sysTenantDao.selectById(appTenantUser.getTenantId());
        if (Boolean.FALSE.equals(sysTenant.getHasApp())) {
            return Result.error(sysTenant.getName() + " 租户未激活 app 应用，无法登录");
        }
        if (Boolean.FALSE.equals(sysTenant.getActivate())) {
            return Result.error(sysTenant.getName() + " 租户未激活，无法登录");
        }
        // 修改当前用户的租户信息
        currentUser.setTenant(sysTenant);
        AppTenantUserVO vo = new AppTenantUserVO();
        BeanUtils.copyProperties(appTenantUser, vo);
        currentUser.setAppTenantUserVO(vo);

        Subject subject = SecurityUtils.getSubject();
        subject.runAs(new SimplePrincipalCollection(currentUser, subject.getPrincipals().getRealmNames().iterator().next()));
        return Result.ok();
    }

    @Override
    public Result<Object> deriveUserList(AppTenantUserDTO dto, HttpServletResponse response) {
//        if (StringUtils.isNotBlank(dto.getLimitSum())) {
//            dto.setLimitSum("limit " + dto.getLimitSum());
//        }
        try {
            List<AppTenantUser> appTenantUserList = appTenantUserDao.selectList(new QueryWrapper<AppTenantUser>()
//                    .le(!ObjectUtils.isEmpty(dto.getApplyTime()), "apply_time", dto.getApplyTime())
                    .orderByDesc(TableConstant.UPDATE_DATE)
//                    .last(StringUtils.isNotBlank(dto.getLimitSum()), dto.getLimitSum())
            );
            if (appTenantUserList.size() > 0) {
                ExportExcel.analysisExport(response, "委外管理", appTenantUserList, AppTenantUser.class);
                return Result.ok("正在导出!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.error("未查询到数据!");
    }

}